package com.example.service.two

import java.io.*
import java.net.Socket
import java.util.regex.Pattern

class FTPControlSocket(private val host: String, private val port: Int = 21) {
    private lateinit var socket: Socket
    private lateinit var writer: BufferedWriter
    private lateinit var reader: BufferedReader
    private var dataHost: String = ""
    private var dataPort: Int = 0
    private var dataSocket: FTPDataSocket? = null

    /**
     * 连接到FTP服务器
     */
    fun connect(): FTPControlSocket {
        socket = Socket(host, port).apply { soTimeout = 5000 }
        writer = BufferedWriter(OutputStreamWriter(socket.getOutputStream()))
        reader = BufferedReader(InputStreamReader(socket.getInputStream()))
        readResponse() // 读取欢迎信息
        return this
    }

    /**
     * 发送命令并读取响应
     */
    private fun sendCommand(command: String): String {
        writer.write("$command\r\n")
        writer.flush()
        return readResponse()
    }

    /**
     * 读取服务器响应 FTPControlSocket 主要是单行
     */
    private fun readResponse(): String {
        val str = reader.readLine() ?: "Read Error"
        println(str)
        return str
    }


    /**
     * 登录到FTP服务器
     */
    fun login(username: String, password: String): FTPControlSocket {
        // 发送用户名
        val userResponse = sendCommand("USER $username")
        if (!userResponse.startsWith("331") && !userResponse.startsWith("230")) {
            return this  // 处理无效用户或直接登录失败[2,5](@ref)
        }

        // 发送密码（仅当需要密码时）
        if (userResponse.startsWith("331")) {
            val passResponse = sendCommand("PASS $password")
            passResponse.startsWith("230")  // 230表示登录成功[5,6](@ref)
        } else {
            userResponse.startsWith("230")  // 匿名登录直接成功[2](@ref)
        }
        return this
    }

    /**
     * 进入被动模式并获取数据连接的IP和端口
     */
    fun enterPassiveMode(): FTPControlSocket {
        val pasvResponse = sendCommand("PASV")
        if (!pasvResponse.startsWith("227")) {
            throw IOException("PASV command failed: $pasvResponse")
        }
        val ip = pasvResponse.substringAfter("(").substringBefore(")").split(",").map { it.toInt() }
            .toIntArray()
        dataPort = (ip[4] shl 8) + ip[5]
        dataHost = "${ip[0]}.${ip[1]}.${ip[2]}.${ip[3]}"
        dataSocket = FTPDataSocket().apply { connect(dataHost, dataPort) }
        return this
    }

    /**
     * 下载文件
     */
    fun downloadFile(remoteFilePath: String, localFilePath: String): FTPControlSocket {
        sendCommand("RETR $remoteFilePath")
        dataSocket?.downloadFile(remoteFilePath, localFilePath)
        return this
    }

    /**
     * 上传文件
     */
    fun uploadFile(localFilePath: String, remoteFilePath: String): FTPControlSocket {
        sendCommand("STOR $remoteFilePath")
        dataSocket?.uploadFile(localFilePath, remoteFilePath)
        return this
    }

    /**
     * 获取帮助信息
     */
    fun help(): FTPControlSocket {
        sendCommand("HELP")
        return this
    }

    /**
     * 更改工作目录
     */
    fun changeWorkingDirectory(path: String): FTPControlSocket {
        sendCommand("CWD $path")
        return this
    }

    /**
     * 列出当前目录内容
     */
    fun listDirectory(): FTPControlSocket {
        sendCommand("LIST")
        val output = dataSocket?.inputStream?.bufferedReader()?.readText()
        println("Directory Listing:\n$output")
        readResponse()
        return this
    }

    /**
     * 显示当前工作目录
     */
    fun printWorkingDirectory(): FTPControlSocket {
        sendCommand("PWD")
        return this
    }

    /**
     * 创建新目录
     */
    fun makeDirectory(dirName: String): FTPControlSocket {
        sendCommand("MKD $dirName")
        return this
    }

    /**
     * 删除目录
     */
    fun removeDirectory(dirName: String): FTPControlSocket {
        sendCommand("RMD $dirName")
        return this
    }

    /**
     * 删除文件
     */
    fun deleteFile(fileName: String): FTPControlSocket {
        sendCommand("DELE $fileName")
        return this
    }

    /**
     * 重命名文件或目录
     */
    fun renameFile(oldName: String, newName: String): FTPControlSocket {
        sendCommand("RNFR $oldName")
        sendCommand("RNTO $newName")
        return this
    }

    /**
     * 获取文件大小
     */
    fun getFileSize(fileName: String): FTPControlSocket {
        sendCommand("SIZE $fileName")
        return this
    }

    /**
     * 获取文件的最后修改时间
     */
    fun getModificationTime(fileName: String): FTPControlSocket {
        sendCommand("MDTM $fileName")
        return this
    }

    /**
     * 设置传输模式为二进制
     */
    fun setBinaryMode(): FTPControlSocket {
        sendCommand("TYPE I")
        return this
    }

    /**
     * 设置传输模式为ASCII
     */
    fun setAsciiMode(): FTPControlSocket {
        sendCommand("TYPE A")
        return this
    }

    /**
     * 保持连接活跃
     */
    fun noOp(): FTPControlSocket {
        sendCommand("NOOP")
        return this
    }

    /**
     * 退出登录并关闭连接
     */
    fun logout(): Boolean {
        val response = sendCommand("QUIT")
        return response.startsWith("221")
    }

    /**
     * 关闭连接
     */
    fun disconnect() {
        try {
            socket.close()
        } catch (e: IOException) {
            e.printStackTrace()
        }
    }

    // 内部类用于处理数据连接
    private inner class FTPDataSocket {
        private lateinit var socket: Socket
        lateinit var inputStream: InputStream
        lateinit var outputStream: OutputStream

        /**
         * 连接到数据服务器
         */
        fun connect(host: String, port: Int) {
            socket = Socket(host, port)
            inputStream = socket.getInputStream()
            outputStream = socket.getOutputStream()
        }

        /**
         * 下载文件
         */
        fun downloadFile(remoteFilePath: String, localFilePath: String) {
            inputStream.use { input ->
                File(localFilePath).outputStream().use { output ->
                    input.copyTo(output)
                }
            }
            println("Downloaded $remoteFilePath to $localFilePath")
        }

        /**
         * 上传文件
         */
        fun uploadFile(localFilePath: String, remoteFilePath: String) {
            outputStream.use { output ->
                File(localFilePath).inputStream().use { input ->
                    input.copyTo(output)
                }
            }
            println("Uploaded $localFilePath to $remoteFilePath")
        }

        /**
         * 关闭数据连接
         */
        fun close() {
            socket.close()
        }
    }
}